home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / base / net-tool.32- / net-tool / net-tools-1.32-alpha / arp.c next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  15.5 KB  |  642 lines

  1. /*
  2.  * arp        This file contains an implementation of the command
  3.  *        that maintains the kernel's ARP cache.  It is derived
  4.  *        from Berkeley UNIX arp(8), but cleaner and with sup-
  5.  *        port for devices other than Ethernet.
  6.  *
  7.  * NET-TOOLS    A collection of programs that form the base set of the
  8.  *        NET-3 Networking Distribution for the LINUX operating
  9.  *        system.
  10.  *
  11.  * Version:    arp 1.69 (1996-05-17)
  12.  *
  13.  * Maintainer:    Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
  14.  *
  15.  * Author:     Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  16.  *
  17.  * Changes:
  18.  *              Alan Cox        :    modified for NET3
  19.  *              Andrew Tridgell :    proxy arp netmasks
  20.  *              Bernd Eckenfels :    -n option
  21.  *              Bernd Eckenfels :    Use only /proc for display
  22.  *     {1.60}    Bernd Eckenfels :    new arpcode (-i) for 1.3.42 but works 
  23.  *                    with 1.2.x, too
  24.  *     {1.61}    Bernd Eckenfels :    more verbose messages
  25.  *     {1.62}    Bernd Eckenfels :    check -t for hw adresses and try to
  26.  *                    explain EINVAL (jeff)
  27.  *960125 {1.63}    Bernd Eckenfels :    -a print hardwarename instead of tiltle
  28.  *960201 {1.64} Bernd Eckenfels :    net-features.h support
  29.  *960203 {1.65} Bernd Eckenfels :    "#define" in "#if", 
  30.  *                    -H|-A additional to -t|-p
  31.  *960214 {1.66} Bernd Eckenfels :    Fix optarg required for -H and -A
  32.  *960412 {1.67} Bernd Eckenfels :    device=""; is default
  33.  *960514 {1.68}    Bernd Eckenfels :    -N and -D
  34.  *960517 {1.69}    Bernd Eckenfels :    usage() fixed
  35.  *
  36.  *        This program is free software; you can redistribute it
  37.  *        and/or  modify it under  the terms of  the GNU General
  38.  *        Public  License as  published  by  the  Free  Software
  39.  *        Foundation;  either  version 2 of the License, or  (at
  40.  *        your option) any later version.
  41.  */
  42. #include <sys/types.h>
  43. #include <sys/socket.h>
  44. #include <sys/ioctl.h>
  45. #include <net/if.h>
  46. #include <linux/netdevice.h>
  47. #include <linux/if_arp.h>
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #include <errno.h>
  51. #include <ctype.h>
  52. #include <fcntl.h>
  53. #include <string.h>
  54. #include <getopt.h>
  55. #include <unistd.h>
  56. #include "net-support.h"
  57. #include "pathnames.h"
  58. #include "version.h"
  59. #include "config.h"
  60. #include "net-locale.h"
  61.  
  62. #define DFLT_AF    "inet"
  63. #define DFLT_HW    "ether"
  64.  
  65. #define FEATURE_ARP
  66. #include "lib/net-features.h"
  67.  
  68.  
  69. char *Release = RELEASE,
  70.      *Version = "arp 1.69 (1996-05-17)";
  71.  
  72. int opt_n = 0;                /* do not resolve addresses    */
  73. int opt_N = 0;                /* use symbolic names           */
  74. int opt_v = 0;                /* debugging output flag    */
  75. int opt_D = 0;                /* HW-address is devicename     */
  76. struct aftype *ap;            /* current address family    */
  77. struct hwtype *hw;            /* current hardware type    */
  78. int sockfd=0;                /* active socket descriptor     */
  79. int hw_set = 0;                /* flag if hw-type was set (-H)    */
  80. char device[16]="";            /* current device        */
  81. static void usage(void);
  82.  
  83. /* Delete an entry from the ARP cache. */
  84. static int
  85. arp_del(char **args)
  86. {
  87.   char host[128];
  88.   struct arpreq req;
  89.   struct sockaddr sa;
  90. #if HAVE_NEW_SIOCSARP
  91.   struct arpreq_old old_req;
  92. #endif
  93.  
  94.   memset((char *) &req, 0, sizeof(req));
  95.  
  96.   /* Resolve the host name. */
  97.   if (*args == NULL) {
  98.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_hostname, "arp: need host name\n"));
  99.     return(-1);
  100.   }
  101.   strcpy(host, *args);
  102.   if (ap->input(0, host, &sa) < 0) {
  103.     ap->herror(host);
  104.     return(-1);
  105.   }
  106.  
  107.   /* If a host has more than one address, use the correct one! */
  108.   memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
  109.  
  110.   req.arp_flags=0;
  111.   
  112.   if (args[1]) {
  113.     if (strcmp(args[1],"pub")==0)
  114.         req.arp_flags|=ATF_PUBL;
  115.     else
  116.         usage();
  117.   }
  118.  
  119. #if HAVE_NEW_SIOCSARP
  120.   strcpy(req.arp_dev,device);
  121.   memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
  122.  
  123.   /* Call the kernel. */
  124.   if (opt_v)  fprintf(stderr,"arp: SIOCDARP()\n");
  125.   if (ioctl(sockfd, SIOCDARP, &req) < 0) {
  126.     if (errno == EINVAL) {
  127.         if (opt_v)  fprintf(stderr,"arp: OLD_SIOCDARP()\n");
  128.         if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) {
  129.             if (errno != ENXIO) {
  130.                 perror("OLD_SIOCSARP");
  131.                 return(-1);
  132.             }
  133.         } else {
  134.             return(0);
  135.         }
  136.     }
  137.     if (errno == ENXIO) {
  138.         printf(NLS_CATGETS(catfd, arpSet, arp_no_arp, 
  139.             "No ARP entry for %s\n"), host);
  140.         return(-1);
  141.     }
  142.     perror("SIOCDARP");
  143.     return(-1);
  144.   }
  145. #else
  146.   /* Call the kernel. */
  147.   if (opt_v)  fprintf(stderr,"arp: old_SIOCDARP()\n");
  148.   if (ioctl(sockfd, SIOCDARP, &req) < 0) {
  149.     perror("SIOCDARP");
  150.     return(-1);
  151.   }
  152. #endif
  153.  
  154.   return(0);
  155. }
  156.  
  157. /* Get the hardware address to a specified interface name */
  158. static int
  159. arp_getdevhw(char *ifname, struct sockaddr *sa, struct hwtype *hw)
  160. {
  161.   struct ifreq ifr;
  162.   struct hwtype *xhw;
  163.  
  164.   strcpy(ifr.ifr_name, ifname);
  165.   if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
  166.       fprintf(stderr,"arp: cant get HW-Address for `%s': %s.\n", ifname, strerror(errno));
  167.       return(-1);
  168.   }
  169.   if (hw && (ifr.ifr_hwaddr.sa_family!=hw->type)) {
  170.       fprintf(stderr,"arp: protocol type missmatch.\n");
  171.       return(-1);
  172.   }
  173.   memcpy((char *)sa, (char *)&(ifr.ifr_hwaddr), sizeof(struct sockaddr));
  174.  
  175.   if (opt_v) {
  176.       if (!(xhw = get_hwntype(ifr.ifr_hwaddr.sa_family)) || (xhw->sprint==0)) {
  177.         xhw = get_hwntype(-1);
  178.       }
  179.       fprintf(stderr, "arp: device `%s' has HW address %s `%s'.\n",ifname, xhw->name, xhw->sprint(&ifr.ifr_hwaddr));
  180.   }
  181.   return(0);
  182. }
  183.  
  184. /* Set an entry in the ARP cache. */
  185. static int
  186. arp_set(char **args)
  187. {
  188.   char host[128];
  189.   struct arpreq req;
  190. #if HAVE_NEW_SIOCSARP
  191.   struct arpreq_old old_req;
  192. #endif
  193.   struct sockaddr sa;
  194.   int flags;
  195.  
  196.   memset((char *) &req, 0, sizeof(req));
  197.  
  198.   /* Resolve the host name. */
  199.   if (*args == NULL) {
  200.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_hostname, "arp: need host name\n"));
  201.     return(-1);
  202.   }
  203.   strcpy(host, *args++);
  204.   if (ap->input(0, host, &sa) < 0) {
  205.     ap->herror(host);
  206.     return(-1);
  207.   }
  208.  
  209.   /* If a host has more than one address, use the correct one! */
  210.   memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
  211.  
  212.   /* Fetch the hardware address. */
  213.   if (*args == NULL) {
  214.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_need_hw, "arp: need hardware address\n"));
  215.     return(-1);
  216.   }
  217.  
  218.   if (opt_D) {
  219.     if (arp_getdevhw(*args++, &req.arp_ha, hw_set?hw:NULL) < 0)
  220.       return(-1);
  221.   } else {
  222.     if (hw->input(*args++, &req.arp_ha) < 0) {
  223.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_invalidhw, "arp: invalid hardware address\n"));
  224.     return(-1);
  225.     }
  226.   }
  227.   
  228.   /* Check out any modifiers. */
  229.   flags = ATF_PERM;
  230.   while (*args != NULL) {
  231.     if (! strcmp(*args, "temp")) flags &= ~ATF_PERM;
  232.     if (! strcmp(*args, "pub")) flags |= ATF_PUBL;
  233. /*    if (! strcmp(*args, "rarp")) flags |= ATF_RARP;*/
  234.     if (! strcmp(*args, "trail")) flags |= ATF_USETRAILERS;
  235.     if (! strcmp(*args, "netmask")) 
  236.       {
  237.         if (*++args == NULL) usage();
  238.         if (strcmp(*args,"255.255.255.255") != 0)
  239.           {
  240.         strcpy(host, *args);
  241.         if (ap->input(0, host, &sa) < 0) {
  242.             ap->herror(host);
  243.             return(-1);
  244.         }
  245.         memcpy((char *) &req.arp_netmask, (char *) &sa,
  246.                sizeof(struct sockaddr));
  247.         flags |= ATF_NETMASK;
  248.           }
  249.       }
  250.     args++;
  251.   }
  252.  
  253.   if ((flags & ATF_NETMASK) && !(flags & ATF_PUBL))
  254.     usage();
  255.  
  256.   /* Fill in the remainder of the request. */
  257.   req.arp_flags = flags;
  258.  
  259. #if HAVE_NEW_SIOCSARP
  260.   strcpy(req.arp_dev,device);
  261.   memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
  262.  
  263.   /* Call the kernel. */
  264.   if (opt_v)  fprintf(stderr,"arp: SIOCSARP()\n");
  265.   if (ioctl(sockfd, SIOCSARP, &req) < 0) {
  266.     if (errno != EINVAL) {
  267.         perror("SIOCSARP");
  268.         return(-1);
  269.     }
  270.     if (opt_v)  fprintf(stderr,"arp: OLD_SIOCSARP()\n");
  271.     if (ioctl(sockfd, OLD_SIOCSARP, &old_req) < 0) {
  272.         if (errno != EINVAL) {
  273.             perror("OLD_SIOCSARP");
  274.             return(-1);
  275.         }
  276.         perror("SIOCSARP and OLD_SIOCSARP");
  277.         if (flags & ATF_PUBL)
  278.             fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_pub, 
  279.                     "Probably destination is reached via ARP Interface. See arp(8)\n"));
  280.         else
  281.             fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_nopub, 
  282.                     "Probably destination is on different Interface. See arp(8)\n"));
  283.         return(-1);
  284.     }
  285.   }
  286. #else
  287.   /* Call the kernel. */
  288.   if (opt_v)  fprintf(stderr,"arp: old_SIOCSARP()\n");
  289.   if (ioctl(sockfd, SIOCSARP, &req) < 0) {
  290.     perror("SIOCSARP");
  291.     return(-1);
  292.   }
  293. #endif
  294.  
  295.   return(0);
  296. }
  297.  
  298.  
  299. /* Process an EtherFile */
  300. static int
  301. arp_file(char *name)
  302. {
  303.   char buff[1024];
  304.   char *sp, *args[32];
  305.   int linenr, argc;
  306.   FILE *fp;
  307.  
  308.   if ((fp = fopen(name, "r")) == NULL) {
  309.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_cant_open, "arp: cannot open etherfile %s !\n"), name);
  310.     return(-1);
  311.   }
  312.  
  313.   /* Read the lines in the file. */
  314.   linenr = 0;
  315.   while (fgets(buff, sizeof(buff), fp) != (char *)NULL) {
  316.     linenr++;
  317.     if (opt_v == 1) fprintf(stderr, ">> %s", buff);
  318.     if ((sp = strchr(buff, '\n')) != (char *)NULL) *sp = '\0';
  319.     if (buff[0] == '#' || buff[0] == '\0') continue;
  320.  
  321.     argc = getargs(buff, args);
  322.     if (argc < 2) {
  323.         fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_formaterr, 
  324.                         "arp: format error on line %u of etherfile %s !\n"),
  325.             linenr, name);
  326.         continue;
  327.     }
  328.  
  329.     if (arp_set(args) != 0) {
  330.         fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_cant_set,
  331.                         "arp: cannot set entry on line %u of etherfile %s !\n"),
  332.             linenr, name);
  333.     }
  334.   }
  335.  
  336.   (void) fclose(fp);
  337.   return(0);
  338. }
  339.  
  340.  
  341. /* Print the contents of an ARP request block. */
  342. static void
  343. arp_disp_2(char *ip,int type,int arp_flags,char *hwa,char *mask,char *dev)
  344. {
  345.   static int title = 0;
  346.   struct hwtype *xhw;
  347.   struct aftype *xap;
  348.   char *sp;
  349.   struct sockaddr sap; 
  350.   char flags[6];
  351.   
  352.   xhw = get_hwntype(type);
  353.   if (xhw == NULL) 
  354.     xhw = get_hwtype("ether");
  355. /*
  356.  * xap = get_afntype(req->arp_pa.sa_family);
  357.  * if (xap == NULL) 
  358.  */
  359.   xap = get_aftype("inet");
  360.     
  361.   if (title++ == 0) {
  362.     printf(NLS_CATGETS(catfd, arpSet, arp_address,
  363.                "Address\t\t\tHWtype\tHWaddress\t    Flags Mask\t\t  Iface\n"));
  364.   }
  365.   /* Setup the flags. */
  366.   flags[0] = '\0';
  367.   if (arp_flags & ATF_COM) strcat(flags, "C");
  368.   if (arp_flags & ATF_PERM) strcat(flags, "M");
  369.   if (arp_flags & ATF_PUBL) strcat(flags, "P");
  370. /*  if (arp_flags & ATF_RARP) strcat(flags, "R");*/
  371.   if (arp_flags & ATF_USETRAILERS) strcat(flags, "T");
  372.  
  373.   /* This IS ugly but it works -be */
  374.   if (xap->input(0, ip,&sap) < 0)
  375.       sp=ip;
  376.   else
  377.       sp = xap->sprint(&sap, opt_n);
  378.   
  379.   printf("%-23.23s\t%-8.8s", sp, xhw->name);
  380.   printf("%-20.20s%-6.6s%-15.15s %s\n", hwa, flags,mask,dev);
  381. }
  382.  
  383.  
  384. /* Display the contents of the ARP cache in the kernel. */
  385. static int
  386. arp_show(char *name)
  387. {
  388.   char host[100];
  389.   struct sockaddr sa;
  390.   char ip[100];
  391.   char hwa[100];
  392.   char mask[100];
  393.   char line[200];
  394.   char dev[100];
  395.   int type,flags;
  396.   FILE *fp;
  397.   int num,entries=0,showed=0;
  398.  
  399.   host[0]='\0';
  400.   
  401.   if (name != NULL) {
  402.       /* Resolve the host name. */
  403.       strcpy(host, name);
  404.       if (ap->input(0, host, &sa) < 0) {
  405.         ap->herror(host);
  406.         return(-1);
  407.       }
  408.       strcpy(host,ap->sprint(&sa, 1));
  409.   }
  410.   
  411.   /* Open the PROCps kernel table. */
  412.   if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
  413.     perror(_PATH_PROCNET_ARP);
  414.     return(-1);
  415.   }
  416.  
  417.   /* Bypass header -- read until newline */
  418.   if (fgets(line, sizeof(line), fp) != (char *)NULL) {
  419.     strcpy(mask,"-");
  420.     strcpy(dev,"-");
  421.     /* Read the ARP cache entries. */
  422.     for(;fgets(line,sizeof(line),fp);)
  423.     {
  424.         num=sscanf(line,"%s 0x%x 0x%x %s %s %s\n",
  425.                                        ip,&type,&flags,hwa,mask,dev);
  426.         if(num<4)
  427.             break;
  428.         
  429.         entries++;    
  430.         /* if the user specified hw-type differs, skip it */
  431.         if (hw_set && (type != hw->type))
  432.             continue;
  433.             
  434.         /* if the user specified address differs, skip it */
  435.         if (host[0] && strcmp(ip,host))
  436.             continue;
  437.         
  438.         /* if the user specified device differs, skip it */
  439.         if (device[0] && strcmp(dev,device))
  440.             continue;
  441.         showed++;    
  442.         arp_disp_2(ip,type,flags,hwa,mask,dev);
  443.     }
  444.   }
  445.   if (opt_v)
  446.     printf(NLS_CATGETS(catfd, arpSet, arp_sum,
  447.         "Entries: %d\tSkiped: %d\tFound: %d\n"),entries,entries-showed,showed);
  448.   
  449.   if (!showed && (hw_set || host[0] || device[0]))
  450.     printf(NLS_CATGETS(catfd, arpSet, arp_none,
  451.         "arp: in %d entries no match found.\n"),entries);
  452.   (void) fclose(fp);
  453.   return(0);
  454. }
  455.  
  456. static void
  457. version(void)
  458. {
  459.   fprintf(stderr, "%s\n%s\n%s\n",Release,Version,Features);
  460.   NLS_CATCLOSE(catfd)
  461.   exit(-1);
  462. }
  463.  
  464. static void
  465. usage(void)
  466. {
  467.   fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage1,
  468.     "Usage: arp [-vn] [-H type] [-i if] -a [hostname]\n"));
  469.   fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage2,
  470.     "       arp [-v] [-i if] -d hostname [pub]\n"));
  471.   fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage3,
  472.     "       arp [-v] [-H type] [-i if] -s  hostname hw_addr [temp]\n"));
  473.   fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage4,
  474.     "       arp [-v] [-H type] [-i if] -s  hostname hw_addr [netmask nm] pub\n"));
  475.   fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage5,
  476.     "       arp [-v] [-H type] [-i if] -Ds hostname if [netmask nm] pub\n"));
  477.   fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage6,
  478.     "       arp [-vnD] [-H type] [-i if] -f filename\n"));
  479.   NLS_CATCLOSE(catfd)
  480.   exit(-1);
  481. }
  482.  
  483. int
  484. main(int argc, char **argv)
  485. {
  486.   int i, lop, what;
  487.   struct option longopts[]=
  488.   {
  489.     {"verbose",    0,    0,    'v'},
  490.     {"version",    0,    0,    'V'},
  491.     {"display",    0,    0,    'a'},
  492.     {"delete",    0,    0,    'd'},
  493.     {"file",    0,    0,    'f'},
  494.     {"numeric",    0,    0,    'n'},
  495.     {"set",        0,    0,    's'},
  496.     {"protocol",    1,    0,    'A'},
  497.     {"hw-type",    1,    0,    'H'},
  498.     {"device",    0,    0,    'i'},
  499.     {"help",    0,    0,    'h'},
  500.     {"use-device",    0,    0,    'D'},
  501.     {"symbolic",    0,    0,    'N'},
  502.     {NULL,        0,    0,    0}
  503.   };    
  504.              
  505. #if NLS
  506.   setlocale (LC_MESSAGES, "");
  507.   catfd = catopen ("nettools", MCLoadBySet);
  508. #endif
  509.  
  510.   /* Initialize variables... */
  511.   if ((hw = get_hwtype(DFLT_HW)) == NULL) {
  512.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_hw_not_supp,
  513.                     "%s: hardware type not supported!\n"), DFLT_HW);
  514.     NLS_CATCLOSE(catfd)
  515.     return(-1);
  516.   }
  517.   if ((ap = get_aftype(DFLT_AF)) == NULL) {
  518.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_fam_not_supp,
  519.                     "%s: address family not supported!\n"), DFLT_AF);
  520.     NLS_CATCLOSE(catfd)
  521.     return(-1);
  522.   }
  523.   what = -1;
  524.  
  525.   /* Fetch the command-line arguments. */
  526.   /* opterr = 0; */
  527.   while ((i = getopt_long(argc, argv, "A:H:adfp:nsi:t:vh?DNV",longopts, &lop)) != EOF) switch(i) {
  528.     case 'a':
  529.         what = 1;
  530.         break;
  531.  
  532.     case 'd':
  533.         what = 3;
  534.         break;
  535.  
  536.     case 'f':
  537.         what = 2;
  538.         break;
  539.  
  540.     case 'n':
  541.         opt_n = FLAG_NUM;
  542.         break;
  543.     case 'D':
  544.         opt_D = 1;
  545.         break;
  546.     case 'N':
  547.         opt_N = FLAG_SYM;
  548.         fprintf(stderr,"arp: -N not yet supported.\n");
  549.         break;
  550.     case 'A':
  551.     case 'p':
  552.         ap = get_aftype(optarg);
  553.         if (ap == NULL) {
  554.             fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_unkn_addr,
  555.                             "arp: %s: unknown address family.\n"),
  556.                 optarg);
  557.             NLS_CATCLOSE(catfd)
  558.             exit(-1);
  559.         }
  560.         break;
  561.  
  562.     case 's':
  563.         what = 4;
  564.         break;
  565.  
  566.     case 'H':
  567.     case 't':
  568.         hw = get_hwtype(optarg);
  569.         if (hw == NULL) {
  570.             fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_unkn_hw,
  571.                             "arp: %s: unknown hardware type.\n"),
  572.                 optarg);
  573.             NLS_CATCLOSE(catfd)
  574.             exit(-1);
  575.         }
  576.         hw_set = 1;
  577.         break;
  578.     case 'i':
  579.         strncpy(device,optarg,sizeof(device)-1);
  580.         device[sizeof(device)-1]='\0';
  581.         break;
  582.  
  583.     case 'v':
  584.         opt_v = 1;
  585.         break;
  586.  
  587.     case 'V':
  588.         version();
  589.  
  590.     case '?':
  591.     case 'h':
  592.     default:
  593.         usage();
  594.   }
  595.  
  596.   if (ap->af != AF_INET) {
  597.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_wrong_af,
  598.                     "arp: %s: kernel only supports 'inet'.\n"),
  599.             ap->name);
  600.     NLS_CATCLOSE(catfd)
  601.     exit(-1);
  602.   }
  603.   if (hw->alen <= 0) {
  604.     fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_wrong_hw,
  605.                     "arp: %s: hardware type without ARP support.\n"),
  606.             hw->name);
  607.     NLS_CATCLOSE(catfd)
  608.     exit(-1);
  609.   }
  610.   if ((sockfd = socket(AF_INET,SOCK_DGRAM,0)) <0)
  611.   {
  612.       perror("socket");
  613.     NLS_CATCLOSE(catfd)
  614.       exit(-1);
  615.   }
  616.  
  617.   /* Now see what we have to do here... */
  618.   switch(what) {
  619.     case 1:        /* show an ARP entry in the cache */
  620.         what = arp_show(argv[optind]);
  621.         break;
  622.  
  623.     case 2:        /* process an EtherFile */
  624.         what = arp_file(argv[optind]);
  625.         break;
  626.  
  627.     case 3:        /* delete an ARP entry from the cache */
  628.         what = arp_del(&argv[optind]);
  629.         break;
  630.  
  631.     case 4:        /* set an ARP entry in the cache */
  632.         what = arp_set(&argv[optind]);
  633.         break;
  634.  
  635.     default:
  636.         usage();
  637.   }
  638.  
  639.   NLS_CATCLOSE(catfd)
  640.   exit(what);
  641. }
  642.